#ifndef TLV_INCLUDED
#define TLV_INCLUDED

#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include "com.pb.h"

class TLV
{
public:
	struct header_block {
		char init[4];
		uint32_t size;
		char initz[4];
	};
private:

	header_block stringToStruct (std::string const& str)
	{
		header_block theStruct;
		memcpy(&theStruct, str.c_str(), sizeof(header_block));

		if(theStruct.init[0] != 's' || theStruct.init[1] != 'k')
			std::cout << "header panic" << std::endl;

		return theStruct;
	}
	std::string structToString (header_block* theStruct)
	{
		char* tempCstring = new char[sizeof(header_block)+1];
		memcpy(tempCstring, theStruct, sizeof(header_block));
		tempCstring[sizeof(header_block)+1] = '0';
		std::string returnVal(tempCstring, sizeof(header_block));
		delete tempCstring;
		return returnVal;
	}

public:
	TLV(std::string const& packet)
	{
		m_header_block = stringToStruct(packet);
	}
	TLV(uint32_t block_len)
	{
		m_header_block.size = block_len;
		m_header_block.init[0] = 's';
		m_header_block.init[1] = 'k';
		m_header_block.init[2] = 'o';
		m_header_block.init[3] = 'd';
	}
	std::string getHeaderAsString()
	{
		return structToString(&m_header_block);
	}
	uint32_t getSize()
	{
		return m_header_block.size;
	}
private:
	header_block m_header_block;
};

class ReceiveBlock
{
public:
	//True = need more data
	bool parseData(const char* s, size_t n)
	{
		m_blob.append(s,n);
		if( m_blob.size() < sizeof(TLV::header_block))
		{
			return true;
		}
		else
		{
			TLV header(m_blob);
			uint32_t len = header.getSize();
			if(m_blob.size() < (len + sizeof(TLV::header_block)))
			{
				return true;
			}
			else
			{
				m_block = std::string(m_blob, sizeof(TLV::header_block), len);
				m_blob.erase(0, len +  sizeof(TLV::header_block));
				return false;
			}
		}
	}

	bool nextBlock()
	{
		return ! parseData("",0);
	}

	std::string getBlock()
	{
		return m_block;
	}
private:
	std::string m_blob;
	std::string m_block;

};


std::string sendBlock(std::string const& block);
/*
{
	TLV header(block.size());
	std::string data(header.getHeaderAsString());
	data.append(block);
	return data;
}
*/
#endif
